HmJS.$Import('core.element');

/*
---
name: Element.defineCustomEvent
version: 1.0.5-0
description: Allows to create custom events based on other custom events.
license: MIT-style license.
download: http://mootools.net/forge/p/custom_event
source: http://github.com/cpojer/mootools-custom-event/

authors: Christoph Pojer (@cpojer)

requires: [Core/Element.Event]

provides: Element.defineCustomEvent
...
*/

HmJS.register('base.element.definecustomevent', function ($ns) {

	[Element, Window, Document].invoke('implement', { hasEvent: function (event) {
		var events = this.retrieve('events'),
		list = (events && events[event]) ? events[event].values : null;
		if (list) {
			for (var i = list.length; i--; ) {
				if (i in list) {
					return true;
				}
			}
		}
		return false;
	}
	});

	var wrap = function (custom, method, extended, name) {
		method = custom[method];
		extended = custom[extended];

		return function (fn, customName) {
			if (!customName) {
				customName = name;
			}

			if (extended && !this.hasEvent(customName)) {
				extended.call(this, fn, customName);
			}
			if (method) {
				method.call(this, fn, customName);
			}
		};
	};

	var inherit = function (custom, base, method, name) {
		return function (fn, customName) {
			base[method].call(this, fn, customName || name);
			custom[method].call(this, fn, customName || name);
		};
	};

	var events = Element.Events;

	Element.defineCustomEvent = function (name, custom) {

		var base = events[custom.base];

		custom.onAdd = wrap(custom, 'onAdd', 'onSetup', name);
		custom.onRemove = wrap(custom, 'onRemove', 'onTeardown', name);

		events[name] = base ? Object.append({}, custom, {

			base: base.base,

			condition: function (event) {
				return (!base.condition || base.condition.call(this, event)) &&
				(!custom.condition || custom.condition.call(this, event));
			},

			onAdd: inherit(custom, base, 'onAdd', name),
			onRemove: inherit(custom, base, 'onRemove', name)

		}) : custom;

		return this;

	};

	var loop = function (name) {
		var method = 'on' + name.capitalize();
		Element[name + 'CustomEvents'] = function () {
			Object.each(events, function (event, name) {
				if (event[method]) event[method].call(event, name);
			});
		};
		return loop;
	};

	loop('enable')('disable');

});
